/*
 * SymbolsFlow.h
 *
 *  Created on: 2016年8月31日
 *      Author: wll
 */

#ifndef INCLUDE_SYMBOLSFLOW_H_
#define INCLUDE_SYMBOLSFLOW_H_

#include "LanguageSymbols.h"
#include <iostream>

class SymbolsFlow
{
public:
	//get current position symbol, when is end return Symbols::END_SYMBOL
	virtual Symbols GetSymbol() { return this->symbol; }
	//is end of the symbols?
	virtual bool IsEnd()=0;
	//go ahead one position, failed when is end
	virtual bool Advance()
    {
        if(this->IsEnd())
        {
            this->symbol = Symbols::END_SYMBOL;
            return false;
        }
        else
        {
            //如果上一个符号是换行符号,则row++,column=0
            if(this->symbol == Symbols('\n'))
            {
                this->row++;
                this->column = 0;
                this->current_line.clear();
            }
            //处理当前符号
            this->symbol = this->GetNextSymbol();
            this->current_line.push_back(this->symbol);
            this->column++;

            return true;
        }
    }
	//get row no of symbols
	virtual int Row() const { return this->row; }
	//get column no of symbols
	virtual int Column() const { return this->column; }
	//get position of symbols
	virtual int Position() const { return this->position; }
    virtual void GetCurrentLine(vector<Symbols>& line) const
    {
        line.clear();
        for (vector<Symbols>::const_iterator i = this->current_line.begin(); i != this->current_line.end(); ++i)
        {
            line.push_back(*i);
        }
    }

private:
    virtual Symbols GetSymbolByPosition(int position) = 0;
    virtual Symbols GetNextSymbol() = 0;
protected:
	SymbolsFlow()
	{
		this->position = 0;
		this->row = 1;
		this->column = 1;
		this->symbol = Symbols::END_SYMBOL;
	}
protected:
	int position;			//从0开始
	int row;					//从1开始
	int column;				//从1开始
	Symbols symbol;
    vector<Symbols> current_line;
};

class StreamSymbolsFlow  : public SymbolsFlow
{
public:
	StreamSymbolsFlow(std::istream& input) : input_stream(input)
	{
		//初始化为第一个符号
		this->symbol = this->GetSymbolByPosition(0);
        this->current_line.push_back(this->symbol);
	}
	//is end of the symbols?
	bool IsEnd()
	{
		return this->input_stream.eof();
	}

    Symbols GetNextSymbol()
    {
        if (this->input_stream.eof())
        {
            return Symbols::END_SYMBOL;
        }
        else
        {
            this->position++;
            char c = this->input_stream.get();
            return this->input_stream.eof() ? Symbols::END_SYMBOL : Symbols(c);
        }
    }

    Symbols GetSymbolByPosition(int position)
    {
        this->input_stream.seekg(position, ios::beg);
        if (this->input_stream.eof())
        {
            return Symbols::END_SYMBOL;
        }
        else
        {
            char c = this->input_stream.get();
            return this->input_stream.eof() ? Symbols::END_SYMBOL : Symbols(c);
        }
    }

protected:
	std::istream& input_stream;
};

class ArraySymbolsFlow  : public SymbolsFlow
{
public:
	ArraySymbolsFlow(const std::vector<Symbols>& input) : input_symbols(input)
	{
		//初始化为第一个符号
		this->symbol = this->GetSymbolByPosition(0);
        this->current_line.push_back(this->symbol);
	}
	//is end of the symbols?
	bool IsEnd()
	{
		return (this->position >= this->input_symbols.size());
	}

    Symbols GetNextSymbol()
    {
        if (this->IsEnd())
        {
            return Symbols::END_SYMBOL;
        }
        else
        {
            return this->GetSymbolByPosition(++this->position);
        }
    }

    Symbols GetSymbolByPosition(int position)
    {
        return (position >= this->input_symbols.size() || position < 0) ? Symbols::END_SYMBOL : this->input_symbols[position];
    }

protected:
	const std::vector<Symbols>& input_symbols;
};

#endif /* INCLUDE_SYMBOLSFLOW_H_ */
